#include "Lexer.h"

#define NOT_RESERVE current_char != '{' && current_char != '}' && current_char != '[' && current_char != ']' && current_char != '(' && current_char != ')' && current_char != '>' && current_char != ':'

Lexer &Lexer::advance()
{
    pos++;
    if (pos >= text.length())
    {
        current_char = '\0';
        ed = true;
    }
    else
    {
        current_char = text[pos];
    }
    return *this;
}

char Lexer::peek(int len)
{
    if (pos + len >= text.length() || pos + len < 0)
    {
        return '\0';
    }
    return text[pos + len];
}

const std::string Lexer::pick_id()
{
    std::string ret;
    while (NOT_RESERVE && current_char != ' ' && current_char != ' ' && current_char != '\n' && !stop())
    {
        ret += current_char;
        advance();
        //std::cout << (int)current_char << std::endl;
    }
    return ret;
}

void Lexer::skip_comment()
{
    advance().advance();
    while (current_char != '\n')
    {
        advance();
    }
    advance();
}

token Lexer::gt()
{
    advance();
    return token(GT, ">");
}

token Lexer::lparen()
{
    advance();
    return token(LPAREN, "(");
}

token Lexer::rparen()
{
    advance();
    return token(RPAREN, ")");
}

token Lexer::lblock()
{
    advance();
    return token(LBLOCK, "[");
}

token Lexer::rblock()
{
    advance();
    return token(RBLOCK, "]");
}

token Lexer::lbracket()
{
    advance();
    return token(LBRACKET, "{");
}

token Lexer::rbracket()
{
    advance();
    return token(RBRACKET, "}");
}

token Lexer::txt()
{
    std::string ret;
    while (NOT_RESERVE && current_char != '\n' && !stop())
    {
        ret += current_char;
        advance();
    }
    return token(TEXT, ret);
}

token Lexer::background()
{
    return token(BACKGROUND, "background");
}

token Lexer::end()
{
    return token(END, "end");
}

token Lexer::colon()
{
    advance();
    return token(COLON, ":");
}


token Lexer::branch()
{
    return token(BRANCH, "branch");
}

token Lexer::minus()
{
    advance();
    return token(MINUS, "-");
}

void Lexer::skip_space(){
    while(current_char == ' '|| current_char == '   '){
        advance();
    }
    if(current_char=='\n'){
        advance();
    }
}

token Lexer::next_token()
{
    while (current_char != '\0')
    {
        if(current_char == '\n'){
            advance();
            continue;
        }
        if (current_char == '>')
        {
            return gt();
        }
        else if (current_char == '(')
        {
            return lparen();
        }
        else if (current_char == ')')
        {
            return rparen();
        }
        else if (current_char == '[')
        {
            return lblock();
        }
        else if (current_char == ']')
        {
            return rblock();
        }
        else if (current_char == '{')
        {
            return lbracket();
        }
        else if (current_char == '}')
        {
            return rbracket();
        }
        else if (current_char == '-')
        {
            return minus();
        }else if(current_char == ':'){
            return colon();
        }else if(current_char == ' ' || current_char == '   '){
            skip_space();
            continue;
        }
        else if (peek(-1) == '>')
        {
            auto s = pick_id();
            if (s == "background")
            {
                return background();
            }else if(s=="branch"){
                return branch();
            }
            else
            {
                return end();
            }
        }
        else if (current_char == '/' && peek() == '/')
        {
            skip_comment();
            continue;
        }
        else
        {
            return txt();
        }
    }
    return end();
}